package cn.tedu.charging.device.dao.repository.impl;

import cn.tedu.charging.device.dao.repository.AbstractStationCacheRepository;
import cn.tedu.charging.device.dao.repository.StationCacheRepository;
import cn.tedu.charging.device.pojo.po.StationCanalPO;
import cn.tedu.charging.device.pojo.po.StationPO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisCommands;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.GeoOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Repository("GeoAndGeo")
public class StationCacheGeoAndGeoRepositoryImpl
        extends AbstractStationCacheRepository
        implements StationCacheRepository {

    private static final Logger log = LoggerFactory.getLogger(StationCacheGeoAndGeoRepositoryImpl.class);
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void saveAllStation(List<StationPO> stationPOs) {
        GeoOperations geoOperations = redisTemplate.opsForGeo();
        //Map<M, Point> memberCoordinateMap
        //StationPO 是 member ， Point member对应的点
        Map<StationPO,Point> map = new HashMap<>();

        for (StationPO stationPO : stationPOs) {
            //获取经度
            BigDecimal stationLng = stationPO.getStationLng();
            //获取维度
            BigDecimal stationLat = stationPO.getStationLat();

            //BigDecimal 通过toEngineeringString 转换为字符串
            String stringLng = stationLng.toEngineeringString();
            String stringLat = stationLat.toEngineeringString();

            //Double.valueOf 方法 把字符串 转换为 Double类型
            Double doubleLng = Double.valueOf(stringLng);
            Double doubleLat = Double.valueOf(stringLat);

            //通过double 类型的经纬度 创建 Spring-data-redis 对象 Point
            Point point = new Point(doubleLng, doubleLat);

            //把 stationPO member 和 point member对应的点 添加到 map 中
            map.put(stationPO,point);
            //一个一个的保存 不推荐
            //geoOperations.add("stations",point,stationPO);

        }
        //批量保存
        //在 数据库保存多条记录的时候 也要记的尽量用批处理的方式，一次保存多条记录
        //不要循环的 一条一条保存
        //Long add(K key, Map<M, Point> memberCoordinateMap);
        geoOperations.add("stations",map);
        //Long add(K key, GeoLocation<M> location);
    }

    @Override
    public List<StationPO> search(Double lng, Double lat, Double radius) {

        GeoOperations geoOperations = redisTemplate.opsForGeo();

        Circle circle = getCircle(lng, lat, radius);
        GeoResults<RedisCommands.GeoLocation<StationPO>>
                results = geoOperations.radius("stations", circle);

        List<StationPO> stationPOS = new ArrayList<>();

        for (GeoResult<RedisGeoCommands.GeoLocation<StationPO>> result : results) {
            Distance distance = result.getDistance();
            log.debug("距离:{}",distance);
            //GeoResult 里的具体的数据 用 content
            RedisGeoCommands.GeoLocation<StationPO> content =
                    result.getContent();
            log.debug("content:{}",content);
            //name 表示的是 GEOADD  是 member StationPO
            StationPO stationPO = content.getName();
            stationPOS.add(stationPO);
        }
        return stationPOS;
    }

    @Override
    public void update(StationCanalPO stationCanalPO) {

    }

    @Override
    public void insert(StationCanalPO stationCanalPO) {

    }

    @Override
    public void delete(StationCanalPO stationCanalPO) {

    }

    @Override
    public StationPO getStationInfoById(String stationId) {
        return null;
    }


    /**
     * 子类实现 抽象类的方法 返回  redisTemplate
     * @return
     */
    @Override
    public RedisTemplate getRedisTemplate() {
        return redisTemplate;
    }
}
